package com.company.aspect;

import java.util.Map;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;

import com.company.dao.AuditLog;
import com.company.dao.AuditLogDao;

@Aspect
public class LoggingAspect {

	@Autowired
	private LoggingHelper loggingHelper;
	
	@Autowired
	private AuditLogDao auditLogDAO;

	@Order(1) 
	@Around("com.company.aspect.SystemArchitecture.businessService()")
	public Object handleInServiceLayer(ProceedingJoinPoint pjp) throws Throwable {
		Object object = null; 									
		
		try {
			object = pjp.proceed();
			
		} catch(RuntimeException e) {					
			//TODO: save exception to audit log
			System.out.println("Runtime");
			
			throw new LoggingException("Thrown back from aspect", e);
		} finally {
			
		}
		
		return object; 
	}		
	
	@Order(2) 
	@Around("com.company.aspect.SystemArchitecture.inDataAccessLayer() && !com.company.aspect.SystemArchitecture.auditLogDao()")
	public Object handleInDAOLayer(ProceedingJoinPoint pjp) throws Throwable {				
		NewValuesInfo newValuesInfo = loggingHelper.extractNewValues(pjp);		
		OldValuesInfo oldValuesInfo = loggingHelper.extractOldValues(pjp, newValuesInfo);		
		Map<String, String> mapDiffValues = loggingHelper.compareValues(oldValuesInfo, newValuesInfo);
		Object[] modifiedObjects = loggingHelper.setNewValues(pjp.getArgs(), oldValuesInfo, newValuesInfo);                       						
		
		Object object = pjp.proceed(modifiedObjects);		
		
		AuditLog auditLog = new AuditLog();
		auditLog.setChanges(mapDiffValues.toString());
		
		auditLogDAO.save(auditLog);
		
		return object; 
	}		
}
